Spring Boot 2.0.0参考手册_中文版_持续更新

文章作者:Tyan
博客:noahsnail.com  |  CSDN  |  简书

第一部分:Spring Boot文档

1. 关于文档

Sring参考文档可以通过htmlpdfepub 三种形式得到。最新的文档可以从docs.spring.io/spring-boot/docs/current/reference上得到。

本文档无论是电子版还是打印版,只要你不收取任何费用且在每个副本中包含了版权声明,你就可以自由使用本文档的副本或分发给其它人。

2. 获得帮助

如果在使用Spring Boot中有不会的地方,我们很乐意帮忙!

  • 尝试How-to’s(文档第九部分),里面有最常见问题的解决方案。

  • 学习Spring基础知识——Spring Boot建立在许多其它的Spring工程之上,查看spring.io网站,上面有大量的参考文档。如果你刚开始使用Spring,尝试看这些指南中的一个。

  • 问问题——我们监控着stackoverflow.com中标签为spring-boot的问题。

  • 报告Spring Boot中的bugs请到github.com/spring-projects/spring-boot/issues

Spring Boot是开源的,包括文档!如果你在文档中发现了问题;或你想改进它们,请参与进去。

3. 第一步

如果你准备开始学习Spring Boot或通常来说的Spring,从这里开始!

  • 从零开始: 概述 | 要求 | 安装

  • 学习指南: 第一部分 | 第二部分

  • 运行例子: 第一部分 | 第二部分

4. 使用Spring Boot

准备好开始使用Spring Boot了?不用担心。

  • 构建系统:Maven | Gradle | Ant | Starters

  • 最佳实践:Code Structure | @Configuration | @EnableAutoConfiguration | Beans and Dependency Injection

  • 运行代码:IDE | Packaged | Maven | Gradle

  • 打包应用:Production jars

  • Spring Boot命令行:Using the CLI

5. 了解Spring Boot特性

需要更多关于Spring Boot核心特性的细节?看下面。

  • 核心特性:SpringApplication | External Configuration | Profiles | Logging

  • Web应用:MVC | Embedded Containers

  • 消息:Overview | JMS

  • 测试:Overview | Boot Applications | Utils

  • 扩展:Auto-configuration | @Conditions

6. 变为产品

当你准备将你的Spring Boot应用变成产品时,给你推荐一些你可能喜欢的小技巧。

  • 管理端点:Overview | Customization

  • 链接选择:HTTP | JMX | SSH

  • 监控:Metrics | Auditing | Tracing | Process

7. 高级课题

最后,我们有一些课题给高级用户。

  • 部署Spring Boot应用:Cloud Deployment | OS Service

  • 构建工具插件:Maven | Gradle

  • 附录:Application Properties | Auto-configuration classes | Executable Jars

Part II 开始

如果你刚开始学习Spring Boot或通常所说的Spring,这部分就是为你准备的!这部分中我们回答了基本的”what?”,”how”,”why?”问题,并在安装说明中介绍Spring Boot。我们将构建第一个Spring Boot应用,讨论一些我们遵循的核心原则。

8. Spring Boot介绍

Spring Boot 使创建独立的、产品级的、基于Spring的应用变得更容易,你只需要运行run即可。我们采用不变的Spring平台和第三方库,因此你可以几乎无差别的使用Spring Boot。大多数Spring Boot应用只需要很少的Spring配置。

你可以使用Spring Boot创建Java应用,用java-jar或更传统的war包来部署应用。我们也提供了运行”Spring脚本”的命令行工具。

我们的主要目标是:

  • 为所有Spring开发者提供一个从根本上更迅速可用的入门经验。

  • 坚持开箱即用,当默认设置不满足需求时可以快速避免默认设置。

  • 为具有许多类的工程提供一系列常用的非功能特性(例如嵌入式服务器、安全、度量、健康检查、外部配置)。

  • 绝对没有XML配置代码产生和XML配置需求。

9. 系统需求

By default, Spring Boot 2.0.0.BUILD-SNAPSHOT requires Java 7 and Spring Framework 5.0.0.BUILD-SNAPSHOT or above. You can use Spring Boot with Java 6 with some additional configuration. See Section 80.11, “How to use Java 6” for more details. Explicit build support is provided for Maven (3.2+) and Gradle (1.12 or 2.x). Gradle 3 is not supported.

默认情况下,Spring Boot 2.0.0.BUILD-SNAPSHOT需要Java 7和Spring Framework 5.0.0.BUILD-SNAPSHOT及以上。你可以通过一些额外配置在Java 6下使用Spring Boot。更多细节请看80.11小节,”怎样使用Java 6”。明确的构建支持有Maven (3.2+)和Gradle (1.12 or 2.x),不支持Gradle 3。

Although you can use Spring Boot with Java 6 or 7, we generally recommend Java 8 if at all possible.

 

虽然你可以在Java 6或Java 7下使用Spring Boot,但我们建议尽可能的使用Java 8。

9.1 Servlet容器

下面的嵌入式servlet容器支持开箱即用:

Name Servlet Version Java Version
Tomcat 8 3.1 Java 7+
Tomcat 7 3.0 Java 6+
Jetty 9.3 3.1 Java 8+
Jetty 9.2 3.1 Java 7+
Jetty 8 3.0 Java 6+
Undertow 1.3 3.1 Java 7+

你也可以部署Spring Boot应用到任何兼容Servlet 3.0+的容器。

10. 安装Spring Boot

Spring Boot可以和”经典”的Java开发工具一起使用,也可作为一个命令行工具来进行安装。不管你是需要Java SDK v.16还是更高版本,在开始之前你应该检查你当前安装的Java版本。

1
$ java -version

如果你是Java开发的新手,或你只想尝试Spring Boot,你可能首先想试一下Spring Boot CLI,否则,请读”经典”的安装说明。

虽然Spring Boot兼容Java 1.6,但可能的话,你应该考虑使用Java的最新版本。

10.1 Java开发者的安装说明

你可以使用Spring Boot像使用任何标准Java库一样。简单的在你的classpath中包含恰当spring-boot-*.jar即可。Spring Boot不需要任何特定的工具集成,因此你可以使用任何IDE或文本编辑器;Spring Boot应用没有什么特别的,你可以像其它的Java程序一样来运行和调试。

尽管你可以只拷贝Spring Boot的jars,但通常我们建议你使用一个支持依赖管理的构建工具(例如Maven或Gradle)。

10.1.1 Maven安装

Spring Boot兼容Apache Maven 3.2或以上。如果你没有安装Maven,你可以根据maven.apache.org的说明来安装。

在许多操作系统上Maven都能通过包管理器来安装。如果你是一个OSX Homebrew用户可以通过brew install maven安装。Ubuntu用户可以通过sudo apt-get install maven安装。

Spring Boot依赖使用org.springframework.boot groupId。通常你的Maven POM文件将继承spring-boot-starter-parent工程并声明一个或多个“Starters”依赖。Spring Boot也提供一个可选的Maven插件来创建可执行的jar包。

下面是一个典型的pom.xml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>

<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>

<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

<!-- Package as an executable jar -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

<!-- Add Spring repositories -->
<!-- (you don't need this if you are using a .RELEASE version) -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>

spring-boot-starter-parent是使用Spring Boot的一种极好的方式,但它可能不是一直都合适的。有时你可能需要继承一个不同的父POM,或者你可能不喜欢我们的默认设置。请看13.2.2小节,『没有父POM的情况下使用Spring Boot』是一种可替代的解决方案,它使用了import作用域。

10.1.2 Gradle安装

Spring Boot兼容Gradle 1.12或2.x。推荐使用2.14.1。不支持Gradle 3。如果你没有安装Gradle,你可以根据www.gradle.org/的介绍来安装。

Spring Boot依赖使用org.springframework.boot groupId。通常你的工程会声明一个或多个“Starters”依赖。Spring Boot提供了一个有用的Gradle插件用来简化依赖声明并创建可执行的jar包。

Gradle Wrapper

当你需要构建一个工程时,Gradle Wrapper提供了一种很好的方式来『获得』Gradle。它是一小段脚本和库,并随着你的代码一起提交来引导构建过程。更多细节请看https://docs.gradle.org/2.14.1/userguide/gradle_wrapper.html

10.2 安装Spring Boot CLI

Spring Boot CLI是一个命令行工具,可以用来快速搭建基于Spring的原型。它允许你运行Groovy脚本,这意味着你有一个熟悉的类Java语法,没有很多的样本代码。

你不需要使用CLI来使用Spring Boot但它是开始得到一个基于Spring应用的最快方式。

10.2.1 手动安装

你可以从Spring软件仓库下载Spring CLI发行版:

最新的snapshot distributions也是可获得的。

一旦下载完成,按照存档INSTALL.txt中的 介绍来安装。总结:bin/目录的.zip文件中有一个spring脚本(Windows中是spring.bat),或者你可以使用java -jar运行.jar文件(这个脚本帮你确保正确设置classpath)。

10.2.2 使用SDKMAN!安装

SDKMAN! (The Software Development Kit Manager)能用来管理各种二进制SDKs的多个版本,包括Groovy和Spring Boot CLI。从sdkman.io中得到SDKMAN!并安装Spring Boot:

1
2
3
$ sdk install springboot
$ spring --version
Spring Boot v2.0.0.BUILD-SNAPSHOT

如果你在为CLI开发功能并向很容易的访问你够简单版本,按照这些额外的介绍去做。

1
2
3
4
$ sdk install springboot dev /path/to/spring-boot/spring-boot-cli/target/spring-boot-cli-2.0.0.BUILD-SNAPSHOT-bin/spring-2.0.0.BUILD-SNAPSHOT/
$ sdk default springboot dev
$ spring --version
Spring CLI v2.0.0.BUILD-SNAPSHOT

这将会安装一个名为dev的本地spring实例。它指向你的目标构建位置,因此你每次重新构建Spring Boot,spring将是最新的。

按下面去做你会看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ sdk ls springboot

================================================================================
Available Springboot Versions
================================================================================
> + dev
* 2.0.0.BUILD-SNAPSHOT

================================================================================
+ - local version
* - installed
> - currently in use
================================================================================

10.2.3 OSX Homebrew安装

如果你在Mac上使用Homebrew,安装Spring Boot CLI所有你需要做的是:

1
2
$ brew tap pivotal/tap
$ brew install springboot

Homebrew会在/usr/local/bin目录安装spring

如果你没有看到公式,你安装的brew可能过时了。执行brew update并重新再试一次。

10.2.4 MacPorts安装

如果你在Mac上使用MacPorts,安装Spring Boot CLI所有你需要做的是:

1
$ sudo port install spring-boot-cli

10.2.5 命令行实现

Spring Boot CLI附带的脚本为BASHzsh shells提供了命令行实现。你可以在任何shell中source脚本(也称为spring),或将它放在用户或系统范围内的bash完成初始化。在Debian系统中系统范围内的脚本是在/shell-completion/bash目录中,当新shell启动时,目录下的所有脚本都被执行。如果你装了SDKMAN!,为了手动运行脚本,执行下面的命令:

1
2
3
$ . ~/.sdkman/candidates/springboot/current/shell-completion/bash/spring
$ spring <HIT TAB HERE>
grab help jar run test version

如果你想使用Homebrew或MacPorts安装Spring Boot CLI,命令行完成脚本会自动在shell中注册。

10.2.6 快速Spring CLI例子

这儿有一个真实的简单的web应用,你可以用来测试你的安装。创建一个文件叫app.groovy

1
2
3
4
5
6
7
8
9
@RestController
class ThisWillActuallyRun {

@RequestMapping("/")
String home() {
"Hello World!"
}

}

这儿有一个真实的简单的web应用,你可以用来测试你的安装。创建一个文件叫app.groovy

1
2
3
4
5
6
7
8
9
@RestController
class ThisWillActuallyRun {

@RequestMapping("/")
String home() {
"Hello World!"
}

}

当你第一次运行应用时它需要一段时间,因为要下载依赖。接下来运行会更快。

在你最喜欢的浏览器中输入localhost:8080,你应该会看到下面的结果:

1
Hello World!

10.3 从早期的Spring Boot升级

如果正在升级你的Spring Boot,检查project wiki中的『发布说明』。你将找到升级说明,说明中有每一次发布的特性列表。

为了升级现有的CLI,要使用合适的包管理命令(例如brew upgrade),如果你手动安装的CLI,要按照标准的说明去做,为了移除旧的引用要记住更新你的PATH环境变量。

11. 开发你的第一个Spring Boot应用

我们用Java开发一个简单的Web应用“Hello World!”,通过应用来强调Spring Boot的一些关键特性。由于大多数IDE都支持Maven,因此我们用Maven来构建这个项目。

spring.io网站上有许多使用Spring Boot的“Getting Started”指南。如果你要解决一个特定的问题;先去网站上看一下。

你可以通过到start.spring.io上并从依赖搜索器中选择web启动器来简化下面的步骤。这会自动的产生一个新的工程结构所以你能以正确的方式开始编码。更多细节请看文档。

1
2
3
4
$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
1
2
3
4
$ mvn -v
Apache Maven 3.2.3 (33f8c3e1027c3ddde99d3cdebad2656a31e8fdf4; 2014-08-11T13:58:10-07:00)
Maven home: /Users/user/tools/apache-maven-3.1.1
Java version: 1.7.0_51, vendor: Oracle Corporation

这个例子需要创建它自己的文件夹。接下来的介绍假设你已经创建了合适的文件夹并且文件夹是你的当前目录。

11.1 创建POM文件

我们首先需要创建一个Maven的pom.xml文件。pom.xml是用来构建项目的处方。打开你最喜欢的文本编辑器并添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>myproject</artifactId>
<version>0.0.1-SNAPSHOT</version>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>

<!-- Additional lines to be added here... -->

<!-- (you don't need this if you are using a .RELEASE version) -->
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/snapshot</url>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<url>http://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>

11.2 添加classpath依赖

Spring Boot提供了许多“Starters”,这样可以很容器的在classpath中添加jar包。我们的例子程序已经在POM的parent部分使用了spring-boot-starter-parentspring-boot-starter-parent是一个特别的启动器,它能提供有用的Maven默认设置。它也提供了依赖管理部分,因此你可以对“blessed”依赖忽略其版本标签。

当开发一个特定的应用时,其它的“Starters”简单的提供了你可能需要的依赖。由于我们正在开发一个web应用,我们将添加spring-boot-starter-web依赖——但在那之前,让我们先看一下目前有什么。

1
2
3
$ mvn dependency:tree

[INFO] com.example:myproject:jar:0.0.1-SNAPSHOT

11.3 写代码

为了完成我们的应用,我们需要创建一个简单的Java文件。Maven默认的将从src/main/java编译源码,因此你需要创建文件结构,然后添加名为src/main/java/Example.java的文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.stereotype.*;
import org.springframework.web.bind.annotation.*;

@RestController
@EnableAutoConfiguration
public class Example {

@RequestMapping("/")
String home() {
return "Hello World!";
}

public static void main(String[] args) throws Exception {
SpringApplication.run(Example.class, args);
}

}

尽管这儿没有太多代码,许多正在进行中。让我们一步步浏览这些重要的部分。

11.3.1 @RestController和@RequestMapping注解

Example类中的第一个注解是@RestController。这是一个模式化的注解。它为阅读代码的人提供了暗示,对于Spring而言,这个类有一个特定的任务。在这个例子中,我们的类是一个web @Controller,当web请求到来时,Spring会考虑用它来处理。

@RequestMapping注解提供了『路由』信息。它告诉Spring任何带有路径”/“的HTTP请求应该映射到home方法上。@RestController注解告诉Spring将结果渲染成字符串形式并直接返回给调用者。

@RestController@RequestMapping是Spring MVC注解(它们不是Spring Boot特有的)。更多细节请看Spring参考文档中MVC部分。

11.3.2 @EnableAutoConfiguration注解

第二个类级别的注解是@EnableAutoConfiguration。这个注解告诉Spring Boot基于你添加的jar依赖去”猜”你想怎样配置Spring。由于spring-boot-starter-web添加了Tomcat和Spring MVC,自动配置会假设你正在开发一个web应用并相应的设置Spring。

启动器和自动化配置

自动配置被设计成跟『启动器』能一起工作的很好,但这两个概念没有直接联系。你可以自由的挑选启动器之外的jar依赖,Spring Boot仍会最大程度地自动配置你的应用。

11.3.3 The “main” method

程序的最后部分是main方法。这是一个符合Java应用程序入口规范的标准方法。main方法中委托Spring Boot的SpringApplication类调用run方法。SpringApplication将引导我们的应用启动Spring,Spring将启动自动配置的Tomcat web服务器。我们需要将Example.class作为参数传给run方法,告诉SpringApplication它是主要的Spring组件。args数组会将所有命令行参数传给run方法。

11.4 运行这个例子

此时我们的应用应该工作了。既然我们已经使用了spring-boot-starter-parent POM,那我们有一个有用的run目标,我们使用它来启动应用。在工程的根目录中输入mvn spring-boot:run来启动应用。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ mvn spring-boot:run

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.0.BUILD-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.222 seconds (JVM running for 6.514)

如果你打开一个web浏览器,输入localhost:8080,你应该会看到下面的输出。

1
Hello World!

可以点击ctrl-c退出应用。

11.5 创建一个可执行的jar

通过创建一个在产品中能运行的完整的自包含可执行jar文件来结束我们的例子。可执行jars(有时称为“fat jars”)是包含编译的类和代码运行需要的所有jar依赖的存档文件。

可执行jars和Java

Java没有提供任何标准方法来加载嵌套的jar文件(例如,jar文件本身包含在一个一个jar中)。如果你想分发一个自包含的应用,这可能是个问题。

为了解决这个问题,许多开发者使用“uber” jars。uber jar简单的将所有jars的所有类打包到一个单独的存档文件中。这个方法的问题是很难看到你的应用正在使用的是哪个库。如果多个jars使用了相同的文件名(不同的内容)也是个问题。

Spring Boot采用了一种不同的方法来处理这个问题,允许你真正的直接内嵌jars。

为了创建可执行jar,我们需要添加spring-boot-maven-pluginpom.xml中。在dependencies部分下面插入以下内容:

1
2
3
4
5
6
7
8
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

spring-boot-starter-parent POM包含绑定repackage目标的<executions>配置。如果你没有使用父POM,那你需要自己声明这个配置。更多细节请看插件文档。

保存你的pom.xml并从命令行中运行mvn package

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ mvn package

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building myproject 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] .... ..
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ myproject ---
[INFO] Building jar: /Users/developer/example/spring-boot-example/target/myproject-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.0.0.BUILD-SNAPSHOT:repackage (default) @ myproject ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

如果你看一下目录target你应该看到myproject-0.0.1-SNAPSHOT.jar。这个文件大小应该在10 Mb左右。如果你想看里面的内容,你可以使用:jar tvf

1
$ jar tvf target/myproject-0.0.1-SNAPSHOT.jar

你在target目录中应该也能看到一个更小的名为myproject-0.0.1-SNAPSHOT.jar.original的文件。这是Spring Boot repackage之前Maven创建的最初的jar文件。

为了运行这个应用,要使用java -jar命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ java -jar target/myproject-0.0.1-SNAPSHOT.jar

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.0.0.BUILD-SNAPSHOT)
....... . . .
....... . . . (log output here)
....... . . .
........ Started Example in 2.536 seconds (JVM running for 2.864)

像前面一样,通过点击ctrl-c来退出应用。

12. 接下来读什么

希望这部分内容给你提供了一些Spring Boot的基本知识,让你写了你自己的应用。如果你是一个面向任务的开发人员,你可能想跳到spring.io,找出一些getting started指南来解决特定的『用Spring怎样做』的问题;我们也提供了Spring Boot的How-to参考文档。

Spring Boot repository也有一些你可以运行的例子。例子是独立于其它代码的(运行或使用例子时你不需要构建其它的内容)。

此外,按逻辑接下来是读第三部分,『使用Spring Boot』。如果你真的不耐烦,你也跳过这部分,直接阅读Spring Boot的特性。

Part III. 使用Spring Boot

这一节将会讲述关于应该如何使用Spring Boot的更多细节。它包括许多主题例如构建系统,自动配置和怎么运行自己的应用。我们也讲述一些Spring Boot的最佳实践。虽然没有关于Spring Boot非常特别的东西(它只是另一个你可以使用的库),但接下来的一些建议可以让你的开发过程更容易一点。

如果你刚开始学习Spring Boot,在学习这节之前你可能应该先阅读一下『Getting Started』部分。

13. 构建系统

强烈建议你选择一个支持依赖管理的构建系统,构建系统可以使用发布在『Maven Central』仓库中的工件。我们建议你选择Maven或Gradle。Spring Boot可能也可以与其它的构建系统进行协作(例如Ant),但不能特别好的支持其它的构建系统。

13.1 依赖管理

Spring Boot的每一次发布都会提供它支持的依赖列表。实际应用时,在你的构建配置中不需要提供这些依赖的版本,因为Spring Boot会帮你进行管理。当你升级Spring Boot时,这些依赖也会随之进行升级。

如果有必要的话,你仍可以指定版本并覆盖Spring Boot的推荐。

这个列表包含了所有你在Spring Boot中可以使用的Spring模块,也包含了第三方库的精制列表。这个列表可以当做一个标准可用的Bills of Materials (spring-boot-dependencies),也额外的专门支持Maven和Gradle可用。

Spring Boot的每一次发布都是与Spring框架的基本版本相关的,因此我们强烈建议你在自己使用时不要指定它的版本。

13.2 Maven

Maven用户可以继承spring-boot-starter-parent工程来获得合理的默认配置。父工程提供了下面的特性:

  • Java 1.6作为默认的编译级别。

  • UTF-8源码编码。

  • 依赖管理部分,对于常用的依赖允许你忽略<version>标签,从spring-boot-dependencies继承POM。

  • 合理的资源过滤。

  • 合理的插件配置(exec plugin, surefire, Git commit ID, shade)。

  • 对包括特定配置文件的application.propertiesapplication.yml的合理资源过滤(例如,application-foo.propertiesapplication-foo.yml)。

最后一点:由于默认配置文件采用Spring风格的占位符(${…​}),Maven过滤改成了使用@..@占位符(你可以使用Maven属性resource.delimiter来覆盖)。

13.2.1 继承starter parent

为了配置你的工程继承spring-boot-starter-parent,简单的设置parent

1
2
3
4
5
6
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
</parent>

你应该只需要在这个依赖中指定Spring Boot的版本号。如果你导入额外的starters,你可以安全的忽略这个版本号。

有了这个设置,你也可以通过在你的工程中重写一个属性来覆盖单独的依赖。例如,为了升级另一个Spring Data的发布版本,你将需要在你的pom.xml中添加以下内容:

1
2
3
<properties>
<spring-data-releasetrain.version>Fowler-SR2</spring-data-releasetrain.version>
</properties>

检查spring-boot-dependencies pom支持的属性清单。

13.2.2 没有父POM的情况下使用Spring Boot

不是每个人都喜欢继承spring-boot-starter-parent POM的。你也可以有需要使用的公司的标准父POM,或者你可能更喜欢显式的声明你所有的Maven配置。

如果你不想使用spring-boot-starter-parent,但你仍要保留依赖管理的好处(不是插件管理),你可以使用scope=import依赖:

1
2
3
4
5
6
7
8
9
10
11
12
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

这个设置不允许你使用上面阐述的属性来重写单独的依赖。为了取得同样的效果,你需要在spring-boot-dependencies入口之前在工程的dependencyManagement中的添加一个入口。为了升级另一个Spring Data的发布版本,你将需要在你的pom.xml中添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<dependencyManagement>
<dependencies>
<!-- Override Spring Data release train provided by Spring Boot -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>Fowler-SR2</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

在上面的例子中,我们指定了一个POM但任何依赖类型都可以被重写。

13.2.3 更改Java版本

spring-boot-starter-parent选择了相当保守的Java兼容性。如果你想听从我们的建议,使用更新的Java版本,你可以添加java.version属性。

1
2
3
<properties>
<java.version>1.8</java.version>
</properties>

13.2.4 使用Spring Boot Maven插件

Spring Boot包含了一个Maven插件,这个插件可以将工程打包为一个可执行的jar包。如果你向使用它的话,将它添加到你的<plugins>部分:

1
2
3
4
5
6
7
8
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

如果你想使用Spring Boot的starter parent pom,你只需要添加这个插件,不需要配置它,除非你想更改父POM中的定义的设置。

13.3 Gradle

Gradle用户可以直接在它们的dependencies部分导入starters。不像Maven,这儿不能导入“super parent”来共享一些配置。

1
2
3
4
5
6
7
8
9
10
apply plugin: 'java'

repositories {
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}

dependencies {
compile("org.springframework.boot:spring-boot-starter-web:2.0.0.BUILD-SNAPSHOT")
}

spring-boot-gradle-plugin也可用,并提供了从源码创建可执行jars和运行项目的功能。它也提供了依赖管理,在其它的兼容性之间,允许你忽略任何Spring Boot管理的依赖的版本号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
buildscript {
repositories {
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}

dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.0.BUILD-SNAPSHOT")
}
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'

repositories {
maven { url "http://repo.spring.io/snapshot" }
maven { url "http://repo.spring.io/milestone" }
}

dependencies {
compile("org.springframework.boot:spring-boot-starter-web")
testCompile("org.springframework.boot:spring-boot-starter-test")
}

13.4 Ant

使用Apache Ant+Ivy来创建一个Spring Boot项目是可能的。spring-boot-antlib “AntLib”模块也可以用来帮助Ant创建可执行jars。

为了声明依赖,一个典型的ivy.xml文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
<ivy-module version="2.0">
<info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
<configurations>
<conf name="compile" description="everything needed to compile this module" />
<conf name="runtime" extends="compile" description="everything needed to run this module" />
</configurations>
<dependencies>
<dependency org="org.springframework.boot" name="spring-boot-starter"
rev="${spring-boot.version}" conf="compile" />
</dependencies>
</ivy-module>

一个典型build.xml如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<project
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="myapp" default="build">

<property name="spring-boot.version" value="1.3.0.BUILD-SNAPSHOT" />

<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve pattern="lib/[conf]/[artifact]-[type]-[revision].[ext]" />
</target>

<target name="classpaths" depends="resolve">
<path id="compile.classpath">
<fileset dir="lib/compile" includes="*.jar" />
</path>
</target>

<target name="init" depends="classpaths">
<mkdir dir="build/classes" />
</target>

<target name="compile" depends="init" description="compile">
<javac srcdir="src/main/java" destdir="build/classes" classpathref="compile.classpath" />
</target>

<target name="build" depends="compile">
<spring-boot:exejar destfile="build/myapp.jar" classes="build/classes">
<spring-boot:lib>
<fileset dir="lib/runtime" />
</spring-boot:lib>
</spring-boot:exejar>
</target>
</project>

如果你不想使用spring-boot-antlib模块,请看79.10小节,“Build an executable archive from Ant without using spring-boot-antlib” “How-to”。

13.5 Starters

启动器是一系列你可以包含进自己应用中的实用依赖描述符。你可以得到所有Spring和你需要的相关技术的一站式服务,不需要有搜索样例代码和拷贝粘贴依赖描述符的负担。例如,如果你想开始使用Spring和JPA来进行数据库链接,只需要在你的工程中包含spring-boot-starter-data-jpa依赖,你便可以很好的前行了。

启动器包含许多你需要启动并快速运行一个工程的依赖,并持续支持一系列传递管理的依赖。

What’s in a name

所有的官方启动器都有一个类似的命名模式:spring-boot-starter-**是应用的特性类型。这个命名结构用来在你需要时帮助你发现一个启动器。Maven在许多IDEs中进行了集成,允许你通过名字来搜索依赖。例如,安装了合适的Eclipse或STS插件,你可以简单的在POM编辑器中点击ctrl-space并输入“spring-boot-starter”来查找一个完整的列表。

正如在创建你自己的启动器部分讲述的那样,第三方启动器不应该与spring-boot一起启动,因为它是预留给官方Spring Boot构建的。acme的第三方启动器通过命名为acme-spring-boot-starter

下面的应用启动器由Spring Boot提供,在org.springframework.boot组下:

表13.1. Spring Boot应用启动器

Name Description POM
spring-boot-starter-thymeleaf Starter for building MVC web applications using Thymeleaf views POM
spring-boot-starter-data-couchbase Starter for using Couchbase document-oriented database and Spring Data Couchbase POM
spring-boot-starter-artemis Starter for JMS messaging using Apache Artemis POM
spring-boot-starter-web-services Starter for using Spring Web Services POM
spring-boot-starter-mail Starter for using Java Mail and Spring Framework’s email sending support POM
spring-boot-starter-data-redis Starter for using Redis key-value data store with Spring Data Redis and the Jedis client POM
spring-boot-starter-web Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container POM
spring-boot-starter-data-gemfire Starter for using GemFire distributed data store and Spring Data GemFire POM
spring-boot-starter-activemq Starter for JMS messaging using Apache ActiveMQ POM
spring-boot-starter-data-elasticsearch Starter for using Elasticsearch search and analytics engine and Spring Data Elasticsearch POM
spring-boot-starter-integration Starter for using Spring Integration POM
spring-boot-starter-test Starter for testing Spring Boot applications with libraries including JUnit, Hamcrest and Mockito POM
spring-boot-starter-jdbc Starter for using JDBC with the Tomcat JDBC connection pool POM
spring-boot-starter-mobile Starter for building web applications using Spring Mobile POM
spring-boot-starter-validation Starter for using Java Bean Validation with Hibernate Validator POM
spring-boot-starter-hateoas Starter for building hypermedia-based RESTful web application with Spring MVC and Spring HATEOAS POM
spring-boot-starter-jersey Starter for building RESTful web applications using JAX-RS and Jersey. An alternative to spring-boot-starter-web POM
spring-boot-starter-data-neo4j Starter for using Neo4j graph database and Spring Data Neo4j POM
spring-boot-starter-websocket Starter for building WebSocket applications using Spring Framework’s WebSocket support POM
spring-boot-starter-aop Starter for aspect-oriented programming with Spring AOP and AspectJ POM
spring-boot-starter-amqp Starter for using Spring AMQP and Rabbit MQ POM
spring-boot-starter-data-cassandra Starter for using Cassandra distributed database and Spring Data Cassandra POM
spring-boot-starter-social-facebook Starter for using Spring Social Facebook POM
spring-boot-starter-jta-atomikos Starter for JTA transactions using Atomikos POM
spring-boot-starter-security Starter for using Spring Security POM
spring-boot-starter-mustache Starter for building MVC web applications using Mustache views POM
spring-boot-starter-data-jpa Starter for using Spring Data JPA with Hibernate POM
spring-boot-starter Core starter, including auto-configuration support, logging and YAML POM
spring-boot-starter-groovy-templates Starter for building MVC web applications using Groovy Templates views POM
spring-boot-starter-freemarker Starter for building MVC web applications using FreeMarker views POM
spring-boot-starter-batch Starter for using Spring Batch POM
spring-boot-starter-social-linkedin Stater for using Spring Social LinkedIn POM
spring-boot-starter-cache Starter for using Spring Framework’s caching support POM
spring-boot-starter-data-solr Starter for using the Apache Solr search platform with Spring Data Solr POM
spring-boot-starter-data-mongodb Starter for using MongoDB document-oriented database and Spring Data MongoDB POM
spring-boot-starter-jooq Starter for using jOOQ to access SQL databases. An alternative to spring-boot-starter-data-jpa or spring-boot-starter-jdbc POM
spring-boot-starter-jta-narayana Spring Boot Narayana JTA Starter POM
spring-boot-starter-cloud-connectors Starter for using Spring Cloud Connectors which simplifies connecting to services in cloud platforms like Cloud Foundry and Heroku POM
spring-boot-starter-jta-bitronix Starter for JTA transactions using Bitronix POM
spring-boot-starter-social-twitter Starter for using Spring Social Twitter POM
spring-boot-starter-data-rest Starter for exposing Spring Data repositories over REST using Spring Data REST POM

除了应用启动器之外,下面的启动器可以用来添加产品准备功能:

Table 13.2. Spring Boot 产品启动器

Name Description Pom
spring-boot-starter-actuator Starter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application Pom

最后,如果你想排除或交换特定的技术方面,Spring Boot也包括一些可以使用的启动器:

Table 13.3. Spring Boot 技术启动器

Name Description Pom
spring-boot-starter-undertow Starter for using Undertow as the embedded servlet container. An alternative to spring-boot-starter-tomcat Pom
spring-boot-starter-jetty Starter for using Jetty as the embedded servlet container. An alternative to spring-boot-starter-tomcat Pom
spring-boot-starter-logging Starter for logging using Logback. Default logging starter Pom
spring-boot-starter-tomcat Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web Pom
spring-boot-starter-log4j2 Starter for using Log4j2 for logging. An alternative to spring-boot-starter-logging Pom

对于额外的社区共享的启动器,请看GitHub上the spring-boot-starters模块的README file

14. 组织你的代码

Spring Boot工作时不要求任何特定的代码布局,但是有一些最佳实践还是很有帮助的。

14.1 使用“default”包

当一个类没有包含一个package声明时,它当做是在default package中。通常情况下不建议使用default package,应该避免使用它。当Spring Boot应用使用@ComponentScan@EntityScan@SpringBootApplication它会引起一些特别的问题,因为Spring Boot会读取每个jar中的每个类。

我们建议你遵循Java推荐的包命名规范,使用一个反转的域名(例如,com.example.project)。

14.2 定义主应用类

通常我们建议你将你的主应用类放在其它类之上的根包中。@EnableAutoConfiguration注解经常放在你的主类(main class)中,对于某些像它隐式的定义了一个基search package,例如,如果你正在写一个JPA应用,@EnableAutoConfiguration注解的类所在的包将被用来搜索@Entity项。

根包的应用也允许使用@ComponentScan注解而不需要指定basePackage特性。如果你的主类是在根包中,你也可以使用@SpringBootApplication注解。

下面是一个典型的布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
com
+- example
+- myproject
+- Application.java
|
+- domain
| +- Customer.java
| +- CustomerRepository.java
|
+- service
| +- CustomerService.java
|
+- web
+- CustomerController.java

Application.java文件会声明main方法和基本的@Configuration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.myproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}

15. 配置类

Spring Boot支持基于Java的注解。尽管可以通过XML源调用SpringApplication.run()方法,但我们通常建议你主要的源是一个@Configuration类。

网上已经发布了许多使用XML配置来进行Spring配置的例子。但要尽可能的尝试使用等价的Java注解。搜索enable*注解是一个好的开端。

15.1 导入额外的配置类

你不必将所有的@Configuration放到一个单独的类中。可以使用@Import注解来导入额外的配置类。或者,你可以使用@ComponentScan来自动获得所有的Spring组件,包括@Configuration类。

15.2 导入XML配置

如果你绝对的必须使用基于XML的配置,我们推荐你仍然从@Configuration类开始。你可以使用额外的@ImportResource注解来加载XML配置文件。

16. 自动配置

Spring Boot自动配置会基于你添加的jar依赖试图自动配置你的Spring应用。例如,如果HSQLDB在你的classpath中,并且你没有手动的配置任何数据库连接beans,我们将会在自动配置一个内存中的数据库。

你需要通过添加@EnableAutoConfiguration@SpringBootApplication注解到你的@Configuration类中的一个来选择性的加入自动配置。

你应该仅添加一个@EnableAutoConfiguration注解。我们通常建议你将它添加到你主要的@Configuration类中。

16.1 逐渐替换自动配置

自动配置是非入侵性的,在任何时候你都可以开始定义你自己的配置来替换自动配置的指定部分。例如,如果你要添加你自己的DataSource bean,默认嵌入的数据库支持将会退出。

如果你需要找出当前正在应用的自动配置和为什么,你可以用--debug开关来启动你的应用。这将会使核心日志的输出级别变为debug级别并输出一个自动配置报告到控制台。

16.2 禁用特定的自动配置

如果你发现正在应用特定的你不想使用的自动配置类,你可以使用@EnableAutoConfiguration注解的exclude特性来禁用它们。

1
2
3
4
5
6
7
8
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.autoconfigure.jdbc.*;
import org.springframework.context.annotation.*;

@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}

如果这个类不在classpath中,你可以使用这个注解的excludeName特性并指定全限定名来代替。最后,你也可以通过spring.autoconfigure.exclude属性来排除,从而控制自动配置类的列表。

你也可以在注解级别或使用属性来定义排除项。

17. Spring Beans和依赖注入

你可以自由的使用任何标准的Spring框架技术来定义你的beans和它们注入的依赖。为了简便,我们经常使用@ComponentScan来发现你的beans,结合@Autowired构造函数注入也工作的很好。

如果你根据上面的建议组织你代码(将你的应用类放在根包中),你可以添加@ComponentScan注解而不需要任何参数。你所有的应用组件(@Component@Service@Repository@Controller等等)将会作为Spring bean进行自动注册。

下面是一个@Service Bean的例子,通过使用构造函数注入来获得RiskAssessor bean。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class DatabaseAccountService implements AccountService {

private final RiskAssessor riskAssessor;

@Autowired
public DatabaseAccountService(RiskAssessor riskAssessor) {
this.riskAssessor = riskAssessor;
}

// ...

}

注意使用构造函数注入允许riskAssessor字段标记为final,意味着它接下来不能被修改。

18. 使用@SpringBootApplication注解

许多Spring Boot的开发者总是在它们的主类上加上@Configuration@EnableAutoConfiguration@ComponentScan注解。由于这些注解频繁的在一起使用(尤其是你遵循上面的最佳实践时),Spring Boot提供了一个方便的@SpringBootApplication注解来代替它们。

@SpringBootApplication注解等价于使用@Configuration@EnableAutoConfiguration@ComponentScan以及它们的默认特性:

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.example.myproject;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication // same as @Configuration @EnableAutoConfiguration @ComponentScan
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}

@SpringBootApplication也提供了别名来定制@EnableAutoConfiguration@ComponentScan的特性。

19. 运行你自己的应用

将应用打包成jar并使用内嵌HTTP服务器的一个最大优势是你可以在任何地方运行你的程序。调试Spring Boot应用也很容易;你不必指定任何特定的IDE插件或扩展。

这一节只包含基于jar的打包,如果你想选择将你的应用打包成war文件,你应该参考你的服务器和IDE文档。

19.1 从IDE运行

你可以在你的IDE中运行一个Spring Boot应用将像运行一个简单的Java应用一样,然而,首先你需要导入你的工程。导入步骤根据你的IDE和构建系统会有所变化。大多数IDE可以直接导入Maven工程,例如Eclipse用户可以选择从File菜单选择Import…​Existing Maven Projects

如果你不能直接将工程导入你的IDE中,你可以使用构建插件生成一个IDE元数据。Maven中包含Eclipse和IDEA的插件;Gradle有各种IDEs的插件。

如果你偶然的运行一个web应用两次,你会看到一个Port already in use错误。为了确保任何现有的实例被关闭,STS用户可以使用Relaunch按钮而不是Run按钮。

19.2 运行一个打包的应用

如果你使用Spring Boot的Maven或Gradle插件来创建一个可执行的jar包,你可以通过使用java -jar来运行你的应用。例如:

1
$ java -jar target/myproject-0.0.1-SNAPSHOT.jar

它也支持以远程调试模式运行一个打包的应用。这允许你在打包的应用中添加一个调试器:

1
$ java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=8000,suspend=n -jar target/myproject-0.0.1-SNAPSHOT.jar

19.3 使用Maven插件

Spring Boot Maven插件包含一个run目标,可以用来快速编译并运行你的应用。应用以exploded形式运行,就像在IDE中运行一样。

1
$ mvn spring-boot:run

你也可以使用有用的操作系统环境变量:

1
$ export MAVEN_OPTS=-Xmx1024m -XX:MaxPermSize=128M

19.4 使用Gradle插件

Spring Boot Gradle插件也包含一个bootRun任务,它可以以exploded方式运行你的应用。当你导入spring-boot-gradle-plugin时,可以添加bootRun任务:

1
$ gradle bootRun

你也可以使用有用的操作系统环境变量:

1
$ export JAVA_OPTS=-Xmx1024m -XX:MaxPermSize=128M

19.5 热交换

由于Spring Boot应用只是普通的Java应用,JVM热交换应该是开箱即用的。JVM热交换可以替换的字节码有限制,一个更全面的解决方案是JRebel或Spring Loaded工程。spring-boot-devtools模块也支持快速的应用重启。

更多细节请看20章,下面的开发者工具部分和怎样热交换部分。

20. 开发者工具

Spring Boot包含额外的工具集合,可以使应用开发的过程更方便一点。spring-boot-devtools模块可以包含进任何工程,用来提供额外的程序调试特性。为了添加工具支持,简单的添加模块依赖到你的构建系统中:

Maven.

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

Gradle.

1
2
3
dependencies {
compile("org.springframework.boot:spring-boot-devtools")
}

当运行一个完整的打包应用时,开发者工具会自动失效。如果你的应用是通过java -jar启动的,或者是通过一个特定的类加载器启动的,那它会被当做一个『产品级应用』。将依赖标记为optional是阻止开发工具间接应用到使用你应用的其它模块的最佳实践。Gradle不支持optional依赖开箱即用,同时你可能想看看propdeps-plugin

再打包文件默认不包含开发者工具。如果你想使用某些远程开发者工具特性,你需要让excludeDevtools构建属性包含它。Maven和Gradle插件都支持这个属性。

20.2 自动重启

classpath中的文件修改时,使用spring-boot-devtools的应用会自动重启。当使用IDE开发时,这是一个很有用的功能,因为代码改变时它能快速的进行反馈。默认情况下,会监控classpath指向的文件夹中任何条目的变化。注意某些资源例如静态资源和视图模板不需要重启应用。

触发重启

作为DevTools监视器classpath中的资源,触发重启的唯一方式是更新classpath。引起classpath更新的方式取决于你使用的IDE。在Eclipse中,保存一个修改的文件将引起classpath更新并触发重启事件。在IntelliJ IDEA中,构建工程(Build → Make Project)将会有同样的效果。

 

只要启用了分支,你也可以通过支持的构建系统启动你的应用(例如,Maven和Gradle),因为DevTools需要一个独立的应用类加载器来进行正确操作。当Gradle和Maven在classpath中检测到DevTools时,它们默认的进行了那个工作。

 

当使用LiveReload,自动重启能很好的工作。更多细节请看下面。如果你使用JRebel进行自动重启,将不支持动态的类重加载。其它的开发者工具功能(例如LiveReload和属性覆写)仍能继续使用。

 

DevTools依赖应用上下文关闭钩子来进行重启期间的关闭。如果你禁用了关闭钩子它将不能正确工作(SpringApplication.setRegisterShutdownHook(false))。

 

当决定classpath中输入引起的改变是否应该触发重启时,DevTools会自动忽略命名为spring-bootspring-boot-devtoolsspring-boot-autoconfigurespring-boot-actuatorspring-boot-starter的工程。

 

重启与重载(重新加载)

Spring Boot提供的重启技术是通过两个类加载器进行工作的。加载进基类加载器的类不能改变(例如,那些第三方jar包)。那些你正在开发的类加载进重启类加载器中。当应用重启时,丢弃旧的重启类加载器并创建一个新的。这种方法意味着应用重启时比『冷启动』更快,因为基类加载器已经存在并可用。

如果你发现你的应用重启不够快,或者你碰到了类加载问题,你可以考虑重载技术例如ZeroTurnaround的JRebel。这些工作通过加载时类的重写使它们更适合重载。Spring加载提供了另一种选择,但许多框架都不支持,也不支持商业化。

20.2.1 例外资源

某些资源当它们改变时不一定需要触发重启。例如,Thymeleaf模板可以就地编辑。默认情况下,/META-INF/maven/META-INF/resources/resources/static/public/templates中资源的改变不会触发重启,但会触发实时重载。如果你想定制这些例外项,你可以使用spring.devtools.restart.exclude属性。例如,仅排除/static/public,设置如下:

1
spring.devtools.restart.exclude=static/**,public/**

如果你想保持这些默认,添加额外的例外项,可以使用spring.devtools.restart.additional-exclude属性。

20.2.2 监控其它路径

当你修改不在classpath中的文件时,你可能也想重启或重载你的应用。为了这样做,可以使用spring.devtools.restart.additional-paths属性来监控其它路径上的变化。你可以使用前面描述的spring.devtools.restart.exclude属性来控制其它路径上的变化是否会触发重启或仅触发实时重载。

20.2.3 禁用重启

如果你想使用重启功能你可以通过spring.devtools.restart.enabled属性禁用它。大多数情况下你可以在你的application.properties中设置它(这仍会初始化重启类加载器但它不会监控文件的变化)。

如果你需要完整的禁用重启支持,例如,因为它不能与一个特定的库一起工作,你需要在调用SpringApplication.run(…​)之前设置一个System属性。例如:

1
2
3
4
public static void main(String[] args) {
System.setProperty("spring.devtools.restart.enabled", "false");
SpringApplication.run(MyApp.class, args);
}

20.2.4 使用触发器文件

如果你的IDE可以持续编译变化的文件,你可以只在特定的时间触发重启。为了实现这个功能你可以使用『触发器文件』,当你需要真正触发重启检查时,它是一个你必须要修改文件。修改这个文件只触发重启检查,只有Devtools检测到它必须要做些事情时,重启才会发生。触发器文件应该进行手动更新,或通过IDE插件更新。

为了使用触发器文件需要使用spring.devtools.restart.trigger-file属性。

为了使你所有的工程都表现一样,你需要将spring.devtools.restart.trigger-file设置为全局设置。

20.2.5 定制重启类加载器

像前面的的Restart vs Reload部分所讲的那样,重启功能是通过两个类加载器实现的。对于大多数应用来说这个方法能很好的工作,但是有时候它也会引起一些类加载问题。

默认情况下,IDE中的任何开放的工程都会使用“restart”类加载器进行加载,任何规范的.jar文件都会使用“base”类加载器进行加载。如果你在一个多模块工程中工作,不是每一个模块都导入到你的IDE中,你可能需要定制一些东西。为了实现这个功能你可以创建一个META-INF/spring-devtools.properties文件。

spring-devtools.properties可以包含restart.exclude.restart.include.前缀属性。include元素应该拉进“restart”类加载器中,exclude元素应该推入到“base”类加载器中。属性值是应用到classpath中的一个正则表达式。

例如:

1
2
restart.exclude.companycommonlibs=/mycorp-common-[\\w-]+\.jar
restart.include.projectcommon=/mycorp-myproj-[\\w-]+\.jar

所有属性的键必须是唯一的。只要restart.include.restart.exclude作为一个属性启动,它就被应用。

 

classpath中的所有META-INF/spring-devtools.properties都会被加载。你可以将文件打包进你的工程中,或这个工程使用的库中。

20.2.6 已知的限制

当存在使用标准ObjectInputStream进行反序列化的对象时,重启功能不能很好的工作。如果你需要反序列化数据,你可能需要使用Spring的ConfigurableObjectInputStreamThread.currentThread().getContextClassLoader()

遗憾的是,一些第三方库反序列化时没有考虑上下文类加载器。如果你发现了这样的问题,你需要请求原作者进行修正。

20.3 实时重载

spring-boot-devtools模块包含一个内嵌的实时重载服务器,当资源改变时可以用来触发浏览器重新刷新。实时重载浏览器扩展对于livereload.com中的Chrome,Firefox和Safari而言是可用的。

当你的应用运行时,如果你不想启动实时重载服务器,你可以将spring.devtools.livereload.enabled属性设为false

一次你只可以运行一个实时重载服务器。在启动你的应用之前,确保没有其它的实时重载服务器在运行。如果你从你的IDE中启动多个应用,只有第一个应用有实时重载服务器支持。

20.4 全局设置

通过添加一个名为.spring-boot-devtools.properties的文件到你的$HOME文件夹中(注意文件名以.开头),你可以配置全局开发者工具设置。任何添加到这个文件的属性都将应用到你机器上所有使用开发者工具的Spring Boot应用中。例如,为了配置重启时总是使用一个触发器文件,你需要添加如下内容:

~/.spring-boot-devtools.properties.

1
spring.devtools.reload.trigger-file=.reloadtrigger

20.5 远程应用

Spring Boot开发者工具是不受本地环境限制的,在运行远程应用时你也可以使用一些功能。远程支持是选择性加入的,为了使它起作用你需要确保devtools包含在再打包的文件中:

1
2
3
4
5
6
7
8
9
10
11
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>false</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>

然后你需要设置spring.devtools.remote.secret属性,例如:

1
spring.devtools.remote.secret=mysecret

使spring-boot-devtools在远程应用上起作用是有安全风险的。在产品部署时,你不应该让它支持spring-boot-devtools

远程devtools需要两部分提供支持:一个接收连接的服务器端,一个运行在IDE中的客户端应用。当设置spring.devtools.remote.secret属性时,服务器组件会自动起作用。客户端组件必须手动启动。

20.5.1 运行远程客户端应用

远程客户端应用设计要在你的IDE中运行。你需要运行org.springframework.boot.devtools.RemoteSpringApplication,与要连接的远程工程要使用同样的classpath。传给应用的非可选参数应该是你要连接的远程URL。

例如,如果你在使用Eclipse或STS,你有一个名为my-app的工程,它已经部署到了云计算中,你需要按照下面的步骤去做:

  • Run菜单中选择Run Configurations…​

  • 创建一个新的Java Application “launch configuration”。

  • 浏览my-app工程。

  • 使用org.springframework.boot.devtools.RemoteSpringApplication作为主类。

  • 添加https://myapp.cfapps.ioProgram arguments(或无论你的远程URL是什么)。

因为远程客户端与真实的应用使用的classpath相同,因此它可以直接读取应用属性。这就是spring.devtools.remote.secret属性是怎样读取并传递给服务器进行授权的。

 

为了传输可以加密,密码不能被解析,建议总是使用https://作为连接协议。

 

如果你需要使用代理访问远程应用,配置spring.devtools.remote.proxy.hostspring.devtools.remote.proxy.port属性。

20.5.2 远程更新

远程客户端会像本地重启那样监控你应用的classpath的变化。任何资源的更新都会推送到远程应用并(如果需要的话)触发重启。如果你在迭代一个本地没有的使用云服务的功能,它是非常有帮助的。通常更新和重启比整个重新构建部署更快。

当远程客户端运行时只监控文件。如果在启动远程客户端之前你修改了文件,它将不会推送到远程服务器。

20.5.3 远程调试通道

当在远程应用上分析问题时,Java远程调试是非常有用的。遗憾的是,当你的应用部署离开你的数据中心时,远程调试并不总是能用的。如果你正在使用一个基于容器的技术例如Docker,要设置远程调试也是非常棘手的。

为了帮助解决这些限制,devtools支持在HTTP协议上的远程调试通道。远程客户端提供一个端口为8000的本地服务器,你可以在这上面添加一个远程调试器。一旦建立了连接,调试通道将会在HTTP上发送到远程应用上。如果你想使用一个不同的端口,你可以使用spring.devtools.remote.debug.local-port属性。

你需要确保你的远程应用启动了并且远程调试可用。这经常可以通过配置JAVA_OPTS来完成。例如,在云计算平台你可以添加下面的内容到你的manifest.yml中:

1
2
3
---
env:
JAVA_OPTS: "-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n"

注意你不必向-Xrunjdwp传递address=NNNN选择。如果被忽略Java将会简单的选择一个随机自由的端口。

 

在网上调试一个远程服务可能是非常慢的,你可能需要在你的IDE中添加timeouts。例如,在Eclipse中你可以从Preferences…​选择Java → Debug,并将Debugger timeout (ms)改成更合适的值(60000在大多数情况下都能很好工作)。

21. 将你的应用打包成产品

可执行jars可以用来进行产品部署。当它们是自包含时,理想情况下它们也是适合云部署的。

对于其它的“production ready”功能,例如健康,审计和度量REST或JMX端点;考虑添加spring-boot-actuator。更多细节请看第五部分,“Spring Boot Actuator: Production-ready features”。

22. 接下来读什么

现在你应该对怎么使用Spring Boot以及应该循序的一些最佳实践有了很好的理解。你可以继续学习关于Spring Boot的一些深度功能,或者你可以跳过前面,直接阅读Spring Boot “production ready”方面的内容。

Part IV. Spring Boot特性

这一部分进入Spring Boot细节部分。在这部分你会了解到你想使用和定制的一些重要特性。如果你还没准备好,你可以阅读第二部分“Getting started”和第三部分“Using Spring Boot”,可以对基础知识有个较好的认识。

23. SpringApplication

SpringApplication提供了一种很方便的方式来引导Spring应用,Spring应用可以从main()方法中启动。许多情况下你可以委托给静态方法SpringApplication.run

1
2
3
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}

当你的应用启动时你应该看到类似于下面的东西:

1
2
3
4
5
6
7
8
9
10
11
12
 .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: v1.4.2.RELEASE

2013-07-31 00:08:16.117 INFO 56603 --- [ main] o.s.b.s.app.SampleApplication : Starting SampleApplication v0.1.0 on mycomputer with PID 56603 (/apps/myapp.jar started by pwebb)
2013-07-31 00:08:16.166 INFO 56603 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6e5a8246: startup date [Wed Jul 31 00:08:16 PDT 2013]; root of context hierarchy
2014-03-04 13:09:54.912 INFO 41370 --- [ main] .t.TomcatEmbeddedServletContainerFactory : Server initialized with port: 8080
2014-03-04 13:09:56.501 INFO 41370 --- [ main] o.s.b.s.app.SampleApplication : Started SampleApplication in 2.992 seconds (JVM running for 3.658)

默认情况下会输出INFO日志信息,包括一些相关的启动细节例如启动应用的用户。

23.1 启动失败

如果你的应用启动失败,注册FailureAnalyzers有可能会提供专门的错误信息和解决这个问题的具体行动。例如,如果你启动一个8080端口的web应用并且这个端口已经被占用,你应该会看到类似于下面的内容:

1
2
3
4
5
6
7
8
9
10
11
***************************
APPLICATION FAILED TO START
***************************

Description:

Embedded servlet container failed to start. Port 8080 was already in use.

Action:

Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.

Spring Boot提供了许多FailureAnalyzer实现,你可以很容易添加自己的FailureAnalyzer实现。

如果没有失败分析器能处理这个异常,你仍可以显示完整的自动配置报告,从而更好的理解什么地方出问题了。为了实现这个你需要启用debug属性或启用org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializerDEBUG日志。

例如,如果你使用java -jar运行应用,你可以用下面的形式启用debug属性:

1
$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

23.2 定制Banner

启动时打印的标语可以通过在classpath中添加一个banner.txt文件或者将banner.location设置为banner.txt文件的位置来修改。如果文件是一种不常见的编码方式,你可以设置banner.charset(默认是UTF-8)。除了文本文件之外,你也添加一个banner.gifbanner.jpgbanner.png图像文件到classpath中,或者设置一个banner.image.location属性。图像将被转换成ASCII艺术表示并打印在文本标语之上。

banner.txt内部你可以使用下面的任何占位符:

Table 23.1. Banner变量

Variable Description
${application.version} 你的应用的版本号在MANIFEST.MF中声明。 例如Implementation-Version: 1.0打印成1.0.
${application.formatted-version} MANIFEST.MF中的声明的应用版本号进行格式化显示(加上前缀v并用括号包裹)。例如(v1.0)
${spring-boot.version} 你使用的Spring Boot版本。例如1.4.2.RELEASE.
${spring-boot.formatted-version} 你使用的Spring Boot版本进行格式化显示加上前缀v并用括号包裹)。例如(v1.4.2.RELEASE)
${Ansi.NAME} (or ${AnsiColor.NAME}, ${AnsiBackground.NAME}, ${AnsiStyle.NAME}) NAME是ANSI转义码的名字。更多细节请看AnsiPropertySource
${application.title} MANIFEST.MF中声明的应用标题。例如Implementation-Title: MyApp打印成MyApp.

如果你想自动生成一个标语你可以使用SpringApplication.setBanner(…​)方法。使用org.springframework.boot.Banner接口并实现你自己的printBanner()方法。

你也可以使用spring.main.banner-mode属性来决定标语是否必须在System.out(控制台)上输出,使用配置的日志(log)或一点也不用(off)。

如果你想在你的应用中禁用banner,YAML会将off映射为false,因此要确保添加引用。

1
2
3
spring:
main:
banner-mode: "off"

23.3 定制SpringApplication

如果你不喜欢默认的SpringApplication,你可以创建一个本地实例并定制它。例如,关闭你写的banner:

1
2
3
4
5
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}

 

传给SpringApplication的构造函数参数是Spring beans配置源。在大多数情况下将会引用@Configuration类,但它们也可以引用XML配置或应该扫描的包。

也可以使用application.properties文件配置SpringApplication。更多细节请看24章,『外部配置』。

完整的配置选项列表,请看SpringApplication文档。

23.4 流畅的构建器API

如果你需要构建ApplicationContext分层(多个具有父/子关系的上下文),或者你更喜欢使用fluent的构建器API,你可以使用SpringApplicationBuilder

SpringApplicationBuilder允许你链接多个方法调用,包括允许你创建分层的parentchild方法。

例如:

1
2
3
4
5
new SpringApplicationBuilder()
.sources(Parent.class)
.child(Application.class)
.bannerMode(Banner.Mode.OFF)
.run(args);

当创建ApplicationContext分层时有一些限制,例如,子上下文必须包含web组件,父子上下文将使用同一个Environment。更完整的细节请看SpringApplicationBuilder文档。

23.5 应用事件和监听器

除了平常的Spring框架事件之外,例如ContextRefreshedEventSpringApplication会发送一些其它的应用事件。

ApplicationContext创建之前实际上会触发一些事件,因此你不能使用@Bean来注册这些监听器。你可以通过SpringApplication.addListeners(…​)SpringApplicationBuilder.listeners(…​)方法来注册这些监听器。

如果你想自动注册这些监听器,不管上下文的创建方式,你可以在你的工程中添加META-INF/spring.factories文件,并通过org.springframework.context.ApplicationListener作为key来引用你的监听器。

1
org.springframework.context.ApplicationListener=com.example.project.MyListener

当你的应用运行时,应用事件以下面的顺序发送:

  1. 在运行启动时发送ApplicationStartedEvent,除了监听器和初始化器注册之外,在进行任何处理之前发送。
  2. 当在上下文中使用的Environment已知时,发送ApplicationEnvironmentPreparedEvent,但发送是在上下文创建之前。
  3. 在再刷新启动之前,但在bean定义加载之后,发送ApplicationPreparedEvent
  4. 在再刷新之后,发送ApplicationReadyEvent,任何相关的回调函数都处理完成之后,意味着应用已经准备处理服务请求了。
  5. 如果启动时出现异常,发送ApplicationFailedEvent.

经常你不需要使用应用事件,但知道它们的存在是便利的。Spring Boot内部使用事件来处理大量的任务。

23.6 Web环境

SpringApplication会尝试创建代表你的合适的ApplicationContext类型。默认情况下,会使用AnnotationConfigApplicationContextAnnotationConfigEmbeddedWebApplicationContext,依赖于你是否在开发一个web应用。

使用的决定web environment的算法是相对简单的(基于现有的一些类)。如果你需要覆写默认值你可以使用setWebEnvironment(boolean webEnvironment)

完全控制ApplicationContext类型也是可能的,通过调用setApplicationContextClass(…​)使用。

当在JUnit测试时使用SpringApplication,经常需要调用setWebEnvironment(false)

23.7 访问应用参数

如果你需要访问传进SpringApplication.run(…​)中的应用参数,你可以注入org.springframework.boot.ApplicationArguments bean。ApplicationArguments接口提供了访问原始String[]和转换的optionnon-option参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import org.springframework.boot.*
import org.springframework.beans.factory.annotation.*
import org.springframework.stereotype.*

@Component
public class MyBean {

@Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
// if run with "--debug logfile.txt" debug=true, files=["logfile.txt"]
}

}

Spring Boot也在Spring Environment中注册CommandLinePropertySource。这也允许你使用@Value注解注入单个应对参数。

23.8 使用ApplicationRunner或CommandLineRunner

如果你需要在SpringApplication启动时运行一些特定的代码,你可以实现ApplicationRunnerCommandLineRunner接口。这两个接口以同样方式工作,并有一个单独的run方法,在SpringApplication.run(…​)之前会调用这个run方法。

CommandLineRunner接口提供了对应用参数的访问,应用参数作为一个简单的字符串数组,而ApplicationRunner使用前面描述的ApplicationArguments接口。

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.boot.*
import org.springframework.stereotype.*

@Component
public class MyBean implements CommandLineRunner {

public void run(String... args) {
// Do something...
}

}

另外,如果定义的CommandLineRunnerApplicationRunner beans必须以指定顺序调用,你可以实现org.springframework.core.Ordered接口或org.springframework.core.annotation.Order 注解。

23.9 应用退出

为了确保ApplicationContext在关闭时安全退出, 每个SpringApplication都会在JVM中注册一个关闭钩子。所有的标准Spring生命周期回调函数(例如DisposableBean接口,或@PreDestroy注解)都会被使用。

另外,当应用退出时,如果它们想返回一个特定的退出码,beans可以实现org.springframework.boot.ExitCodeGenerator接口。

23.10 Admin功能

如果应用想启用admin相关的功能,可以指定spring.application.admin.enabled属性。这会在平台MBeanServer上暴露SpringApplicationAdminMXBean。你可以使用这个功能远程的管理你的Spring Boot应用。对于任何服务包裹的实现这是很有用的。

如果你想知道应用运行的HTTP接口,通过关键字local.server.port可以得到这个属性。

 

当启用这个功能时要非常小心,因为MBean会暴露一个关闭应用的方法。

24. 外部配置

Spring Boot允许你进行外部化配置,因此可以将同样的应用代码在不同的环境中运行。你可以使用属性文件,YAML文件,环境变量和命令行参数来进行外部化配置。属性值可以使用@Value注解直接注入到你的beans中,通过Spring的Environment抽象或通过@ConfigurationProperties绑定到结构化对象上来访问。

Spring Boot使用非常特别的PropertySource顺序,这个顺序的设计是为了允许值的合理重写。属性被认为是按照以下顺序:

  1. 根目录下的开发工具全局设置属性(当开发工具激活时为~/.spring-boot-devtools.properties)。
  2. 测试中的@TestPropertySource注解。
  3. 测试中的@SpringBootTest#properties注解特性。
  4. 命令行参数。
  5. SPRING_APPLICATION_JSON中的属性(环境变量或系统属性中的内联JSON嵌入)。
  6. ServletConfig初始化参数。
  7. ServletContext初始化参数。
  8. java:comp/env的JNDI特性。
  9. Java系统属性 (System.getProperties())。
  10. 操作系统环境变量。
  11. RandomValuePropertySource只在random.*中有属性。
  12. jar包之外的指定配置文件的应用属性(application-{profile}.properties和YAML变量)。
  13. jar包之内的指定配置文件的应用属性(application-{profile}.properties和YAML变量)。
  14. jar包之外的应用属性 (application.properties和YAML变量)。
  15. jar包之内的应用属性 (application.properties和YAML变量)。
  16. @Configuration类中的@PropertySource注解 。
  17. 默认属性(通过SpringApplication.setDefaultProperties指定).

为了提供一个具体的例子,假设你开发了一个使用名字属性的@Component

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.stereotype.*
import org.springframework.beans.factory.annotation.*

@Component
public class MyBean {

@Value("${name}")
private String name;

// ...

}

在你的应用路径中(例如在你的jar内部),你可以使用application.propertiesname提供一个合理的默认属性值。当在新环境运行时,application.properties可以在jar外部提供来重写name;对于一次性测试,你可以通过指定的命令行切换来启动(例如java -jar app.jar --name="Spring")。

SPRING_APPLICATION_JSON可以在命令行中通过环境变量提供。例如在UNIX shell中:

1
$ SPRING_APPLICATION_JSON='{"foo":{"bar":"spam"}}' java -jar myapp.jar

在这个例子中,Spring的Environment中会有foo.bar=spam。你也可以在系统变量中提供JSON作为spring.application.json

1
$ java -Dspring.application.json='{"foo":"bar"}' -jar myapp.jar

或命令行参数:

1
$ java -jar myapp.jar --spring.application.json='{"foo":"bar"}'

或JNDI变量java:comp/env/spring.application.json

24.1 配置随机值

当注入随机值时,RandomValuePropertySource是很有用的(例如,注入秘密或测试用例)。它可以产生integerslongsuuidsstrings,例如:

1
2
3
4
5
6
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}

random.int*语法OPEN value (,max) CLOSEOPEN,CLOSE可以是任何字符,value,max是整数。如果提供了max,则value是最小值,max是最大值(不包含)。

24.2 访问命令行属性

默认情况下,SpringApplication会将任何命令行参数(以--开头,例如--server.port=9000)转换成property并将其添加到Spring的Environment中。正如前面提到的那样,命令行属性总是优先于其它的配置源。

如果你想命令行属性添加到Environment中,你可以使用SpringApplication.setAddCommandLineProperties(false)禁用它。

24.3 应用属性文件

SpringApplication会从以下位置的application.properties文件中加载属性并将它们添加到Spring的Environment中:

  1. 当前目录的子目录/config

  2. 当前目录

  3. classpath中的/config

  4. classpath的根目录

这个列表是按优先级排序的(在更高位置的属性会重写定义在更低位置的属性)。

你也可以使用YAML(.yml)文件来代替.properties文件。

如果你不喜欢用application.properties作为配置文件的名字,你可以通过指定spring.config.name环境属性来来改变配置文件的名字。你也可以使用spring.config.location环境属性来引用一个显式的位置(目录位置或文件路径以逗号分隔)。

1
$ java -jar myproject.jar --spring.config.name=myproject

1
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

spring.config.namespring.config.location可以在早期用来决定加载哪一个文件,因此必须被定义为环境属性(通常是操作系统环境,系统属性或命令行参数)。

如果spring.config.location包含目录(相对于文件而言),它们应该以/结尾(在加载之前,在后面添加上从spring.config.name中产生的名字,包括指定配置文件的名字)。在spring.config.location中指定的文件按原样使用,不支持指定配置文件变量,将会被任何指定配置文件的属性覆盖。

默认搜索路径一直用classpath:,classpath:/config,file:,file:config/,不管spring.config.location中的值。搜索路径按从低到高排序(file:config/最高)。如果你指定了自己的位置,它们优先于所有的默认位置并使用同样的从低到高的顺序。这样你可以在application.properties中为你的应用设置默认值(或你可以选择spring.config.name的其它生成文件基本名),在运行时用其它的文件覆盖它,同时保留默认值。

如果你使用环境变量而不是系统属性,大多数操作系统不允许句号分隔的关键字,但你可以用下划线代替(例如,SPRING_CONFIG_NAME代替spring.config.name)。

如果你在容器中运行,那么JNDI属性(在java:comp/env中)或servlet上下文初始化参数也可以用来代替环境变量或系统属性。

24.4 特定的profile属性

除了application.properties文件之外,特定的profile属性也可以使用命名规范application-{profile}.properties来定义。Environment有一系列默认配置文件(默认为[default]),如果没有设置激活的配置文件,会使用默认的配置文件(例如,如果没有激活显式的配置文件,则会加载application-default.properties中的属性)。

特定的profile属性会从相同位置加载application.properties,特定的profile文件总是覆盖非特定的配置文件,无论特定profile文件在你打包的jar内部还是外部。

如果指定了几个配置文件,将会应用最后一个。例如,spring.profiles.active属性指定的配置文件在那些配置的文件之后通过SpringApplication API添加,因此优先级更高。

如果你在spring.config.location中指定了任何文件,那些文件的特定profile版本将不会被考虑。如果你也想使用特定的profile属性,在spring.config.location中使用目录。

24.5 属性中的占位符

当使用application.properties中的值时,会通过现有的Environment进行过滤,因此你可以参考前面定义的值(例如从系统属性中)。

1
2
app.name=MyApp
app.description=${app.name} is a Spring Boot application

你也可以使用这个技术来创建现有的Spring Boot属性的short版本。怎样使用的更多细节请看70.4小节,“Use ‘short’ command line arguments”。

24.6 使用YAML代替Properties

YAML是JSON的超集,它可以用一种非常方便的形式来指定分层配置数据。当你的类路径有SnakeYAML库时,SpringApplication类自动支持YAML作为properties的一个替代品。

如果你使用‘Starters’,SnakeYAML将由spring-boot-starter自动提供。

24.6.1 加载YAML

Spring框架提供了两个类用来方便的加载YAML文档。YamlPropertiesFactoryBean将加载YAML作为PropertiesYamlMapFactoryBean将加载YAML作为Map

例如,下面的YAML文档:

1
2
3
4
5
6
7
environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App

将被转换成这些属性:

1
2
3
4
environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App

YAML列表通过[index]解引用表示为属性的key,例如这个YAML:

1
2
3
4
my:
servers:
- dev.bar.com
- foo.bar.com

将被转换成这些属性:

1
2
my.servers[0]=dev.bar.com
my.servers[1]=foo.bar.com

为了像使用Spring的DataBinder一样(@ConfigurationProperties的功能)绑定这些属性,你需要在类型为java.util.List(或Set)的目标bean中有属性,你需要提供一个setter或用一个可变的值来对它初始化,例如,绑定上面的属性值:

1
2
3
4
5
6
7
8
9
@ConfigurationProperties(prefix="my")
public class Config {

private List<String> servers = new ArrayList<String>();

public List<String> getServers() {
return this.servers;
}
}

24.6.2 在Spring Environment中公开YAML为属性

YamlPropertySourceLoader类可以在Spring的Environment中将YAML作为PropertySource。这允许你使用熟悉的@Value注解和占位符语法来访问YAML属性。

24.6.3 多profile的YAML文档

你可以在单个文件中指定多个特定profile的YAML文档,当应用文档时,通过spring.profiles关键字来表明使用哪个文档。例如:

1
2
3
4
5
6
7
8
9
10
11
12
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production
server:
address: 192.168.1.120

在上面的例子中,如果development profile被激活,server.address的值为127.0.0.1。如果developmentproduction profile不可用,server.address的值为192.168.1.100

当应用上下文启动时,如果没有显式的激活profile,则激活默认的profile。因此在这个YAML文件中我们仅在”default” profile中设置了security.user.password

1
2
3
4
5
6
7
8
server:
port: 8000
---
spring:
profiles: default
security:
user:
password: weak

在这个例子中,密码总是设置的,因为它没有添加到如何profile中,必要时我们必须在其它的profile中显式的对它重新设置:

1
2
3
4
5
server:
port: 8000
security:
user:
password: weak

Spring profiles被设计为使用”spring.profiles”元素可以选择性的用!字符进行否定。如果否定的和非否定的profile指向一个单独的文档,必须至少匹配一个非否定的profile,可能没有否定的profile进行匹配。

24.6.4 YAML缺点

YAML文件不能通过@PropertySource注解进行加载。因此在这种情况下如果你需要加载值,你需要使用属性文件。

24.6.5 合并YAML列表

正如我们上面看到的,任何YAML内容最终都要转换成属性。当通过profile重写“list“属性时,这个过程可能有违直觉。

例如,假设MyPojo对象的namedescription属性默认情况下为空。从FooProperties使用一个MyPojo列表:

1
2
3
4
5
6
7
8
9
10
@ConfigurationProperties("foo")
public class FooProperties {

private final List<MyPojo> list = new ArrayList<>();

public List<MyPojo> getList() {
return this.list;
}

}

考虑下面的配置:

1
2
3
4
5
6
7
8
9
10
foo:
list:
- name: my name
description: my description
---
spring:
profiles: dev
foo:
list:
- name: my another name

如果dev profile没有激活,FooProperties.list将包含一个上面定义的MyPojo输入。然而如果dev profile可用,lists仍只包含一个输入(name为“my another name”,description为空)。这个配置将不能添加第二个MyPojolist中,并且它将不能合并这些项。

当在多个profiles中指定一个集合时,将会使用最高优先级的那个集合(唯一的哪个):

1
2
3
4
5
6
7
8
9
10
11
12
foo:
list:
- name: my name
description: my description
- name: another name
description: another description
---
spring:
profiles: dev
foo:
list:
- name: my another name

在上面的例子中,假设dev profile被激活,FooProperties.list将包含一个MyPojo输入(name为“my another name”,description为空)。

24.7 类型安全的配置属性

Boot提供了一种处理属性的可替代方法,允许强类型的beans管理和验证你的应用的配置。例如:

1
2
3
4
5
6
7
8
9
10
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {

private String username;

private InetAddress remoteAddress;

// ... getters and setters

}

建议添加getters和setters,绑定是通过标准的Java Beans属性描述符,像在Spring MVC中一样。对于不可变类型或那些从String中可直接强制转换的类型,它们是强制性的。只要它们被初始化,maps,集合或数组需要getter方法,但不需要setter方法因为通过绑定起它们可以直接变化。如果有setter,可以创建Maps,集合和数组。Maps和集合可以通过getter扩展,数组扩展需要setter。如果它们有默认的构造函数,或构造函数接收可以从String类型强制转换的值,嵌入的POJO属性也可以创建(因此setter不是强制性的)。一些人使用Lombok项目来自动添加getter和setter。

 

请看@Value@ConfigurationProperties之间的不同。

你也需要在@EnableConfigurationProperties注解中列出要注册的属性类:

1
2
3
4
@Configuration
@EnableConfigurationProperties(ConnectionProperties.class)
public class MyConfiguration {
}

@ConfigurationProperties以那种方式注册时,这个bean将有一个常规的名字:<prefix>-<fqn><prefix>是在@ConfigurationProperties注解中指定的环境关键字的前缀,<fqn>是bean的完整合格的名字。如果注解没有提供任何前缀,则只用bean的完整合格的名字。

在上面的例子中bean名字是connection-com.example.ConnectionProperties,假设ConnectionPropertiescom.example包中。

即使上面的配置会为ConnectionProperties创建一个正规的bean,我们建议@ConfigurationProperties只处理环境,特别是不从上下文中注入其它的beans。已经说过,为了任何带有@ConfigurationProperties注解的bean可以根据Environment属性进行配置,@EnableConfigurationProperties注解也自动应用到你的工程中。确保ConnectionProperties已经是一个bean,你可以简写上面的MyConfiguration

1
2
3
4
5
6
7
@Component
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {

// ... getters and setters

}

这种风格的配置在SpringApplication的外部化YAML配置中工作的尤其好:

1
2
3
4
5
6
7
# application.yml

connection:
username: admin
remoteAddress: 192.168.1.1

# additional configuration as required

为了同@ConfigurationProperties beans一起工作,你可以像任何其它bean一样以相同的方式注入它们:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Service
public class MyService {

private final ConnectionProperties connection;

@Autowired
public MyService(ConnectionProperties connection) {
this.connection = connection;
}

//...

@PostConstruct
public void openConnection() {
Server server = new Server();
this.connection.configure(server);
}

}

使用@ConfigurationProperties也允许你生成IDEs可以使用的元数据文件。更多细节请看附录B,配置元数据附录。

24.7.1 第三方配置

也可以使用@ConfigurationProperties来注解一个类,你也可以在公有的@Bean方法上使用它。当你想绑定属性到你控制之外的第三方组件上时尤其有用。

1
2
3
4
5
@ConfigurationProperties(prefix = "foo")
@Bean
public FooComponent fooComponent() {
...
}

任何定义的带有foo前缀的属性都将以类似于上面的ConnectionProperties例子中的方式映射到FooComponent bean中。

24.7.2 松散绑定

Spring Boot使用一些松散的规则将Environment属性绑定到@ConfigurationProperties beans上,因此不需要在Environment属性名和bean属性名之间进行确切的匹配。常见的有用例子包括破折号分隔(例如,context-path绑定到contextPath),大小写(例如PORT绑定到port,)环境属性。

例如,给定下面的@ConfigurationProperties类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@ConfigurationProperties(prefix="person")
public class OwnerProperties {

private String firstName;

public String getFirstName() {
return this.firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

}

下面的属性名都可以使用:

表24.1. 松散绑定

Property Note
person.firstName 标准的驼峰写法
person.first-name 破折号注解,建议在.properties.yml文件中使用
person.first_name 下划线注解,.properties.yml文件中的可替代写法
PERSON_FIRST_NAME 大写形式。当使用系统变量时推荐

24.7.3 属性转换

当Spring绑定属性到@ConfigurationProperties beans时,它将试图将外部的应用属性强制转换成正确的类型。如果你需要定制类型转换你可以提供一个ConversionService bean(bean id为conversionService),或定制属性编辑器(通过CustomEditorConfigurer bean),或定制Converters(带有@ConfigurationPropertiesBinding注解的bean定义)。

bean要求在应用生命周期中的早期,要确保限制ConversionService使用的依赖。通常,任何你要求的依赖可能在创建时不是完整初始化的。如果你定制的ConversionService不要求配置关键字强制转换,你可能想重新命名你定制的ConversionService,并且只依赖满足@ConfigurationPropertiesBindings的定制转换器。

24.7.4 @ConfigurationProperties验证

Spring Boot会试图验证外部化配置,默认使用JSR-303(如果它在classpath中)。你可以简单的添加JSR-303 javax.validation约束注解到你的@ConfigurationProperties类中:

1
2
3
4
5
6
7
8
9
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {

@NotNull
private InetAddress remoteAddress;

// ... getters and setters

}

为了验证嵌入的属性值,你必须注解相关的字段作为@Valid来触发它的校验。例如,在上面的ConnectionProperties例子上构建:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {

@NotNull
@Valid
private RemoteAddress remoteAddress;

// ... getters and setters

public static class RemoteAddress {

@NotEmpty
public String hostname;

// ... getters and setters

}

}

通过创建一个称为configurationPropertiesValidator的bean定义,你也可以添加定制的Spring Validator@Bean方法应该声明静态的。配置属性验证器在应用生命周期的早期创建,声明@Bean方法为静态方法,允许不必实例化@Configuration类就创建bean。这避免了任何早期实例化可能引起的问题。这儿有一个属性验证的例子因此你可以看一下怎样设置它

spring-boot-actuator模块包含一个端点,这个端点将公开所有的@ConfigurationProperties beans。简单的将你的web浏览器指向/configprops或用等价的JMX端点。更多细节请看产品级功能

24.7.5 @ConfigurationProperties和@Value

@Value是一种核心的容器功能,它不能作为类型安全配置属性提供同样的功能。下面的表中总结了@ConfigurationProperties@Value支持的功能:

功能 @ConfigurationProperties @Value
松散绑定 Yes No
元数据支持 Yes No
SpEL评估 No Yes

如果你为自己的组件定义了一些配置关键字,我们建议你将它们分组到带有@ConfigurationProperties注解的POJO中。也请注意@Value不支持松散绑定,如果你需要用环境变量提供值,它不是一个好的选择。

最后,虽然你可以在@Value中写表达式,但这种表达式不能从应用属性文件中处理。

25. Profiles

Spring Profiles提供了一种隔离部分应用配置的方式,并让这些配置只在特定的环境生效。任何带有@Profile标记的@Component@Configuration在加载时都会受限制:

1
2
3
4
5
6
7
@Configuration
@Profile("production")
public class ProductionConfiguration {

// ...

}

以正常的Spring方式,你可以使用spring.profiles.active Environment属性来指定激活哪一个profiles。你可以在任何常见的方式指定这个属性,例如你可以在你的application.properties中包含它:

1
spring.profiles.active=dev,hsqldb

或在命令行用--spring.profiles.active=dev,hsqldb指定。

25.1 添加激活的profiles

spring.profiles.active属性与其它的属性一样遵循同样的排序规则,最高的PropertySource优先。这意味着你可以在application.properties指定激活的profiles,然后用命令行转换替代它们。

例如,当一个应用具有以下属性且运行时使用--spring.profiles.active=prod转换,proddbprodmq profiles也将被激活:

1
2
3
4
5
6
7
---
my.property: fromyamlfile
---
spring.profiles: prod
spring.profiles.include:
- proddb
- prodmq

记住可以在YAML文档中定义spring.profiles来决定在配置中包含特定的文档。更多细节请看70.7小节,“根据环境更改配置”。

25.2 以编程方式设置profiles

你可以在你的应用运行之前以编程的方式调用SpringApplication.setAdditionalProfiles(…​)来设置激活的profiles。也可以使用Spring的ConfigurableEnvironment接口来激活profiles。

25.3 指定profile的配置文件

application.properties(或application.yml)和通过@ConfigurationProperties引用的文件的特定profiles变种都被当做文件进行加载。更多细节请看24.4小节,“Profile-specific properties”。

26. Logging

Spring Boot所有的内部日志都采用Commons Logging,但开放了底层的日志实现。提供了对Java Util Logging,Log4J2和Logback的默认实现。在每个logger中都预先配置使用控制台作为输出,同时也可用可选的文件输出。

默认情况下,如果使用Starters,Logback将作为日志。也要包含恰当的Logback规则来保证依赖库使用Java Util Logging,Commons Logging,Log4J或SLF4J都能正确工作。

在Java中有许多日志框架可用。不必担心上面的列表看起来有点混乱。通常情况下你不需要改变你的日志依赖,Spring Boot默认情况下能很好的工作。

26.1 Log格式

Spring Boot默认的日志输出看起来如下:

1
2
3
4
5
2014-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253 INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698 INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702 INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

下面的是输出项:

  • Date and Time — 精确到毫秒且容易排序。

  • Log级别 — ERROR,WARN,INFO,DEBUG或TRACE。

  • 进程ID。

  • ---分隔符来区分真正的日志信息的开始。

  • 线程名称 — 用方括号包裹(在控制台输出中经常是缩减的)。

  • Logger名称 — 源类名(经常是简写)。

  • 日志信息。

Logback没有FATAL级别(它映射到ERROR)。

26.2 控制台输出

默认的日志配置会将信息输出到控制台。默认情况下会输出ERRORWARNINFO级别的信息。你也可以通过--debug来启动你的应用,从而启用“debug”模式。

1
$ java -jar myapp.jar --debug

你也可以在application.properties指定debug=true

当启用调试模式时,配置选择的核心logger(嵌入式容器,Hibernate和Spring Boot)来输出更多的信息。启动调试模式不会将你的应用配置成输出所有DEBUG级别的信息。

或者,你可以用--trace标记(或在application.properties中添加trace=true)启动你的应用,从而启用“trace”模式。这将在选择的核心logger中(嵌入式容器,Hibernate模式生成和整个Spring文件夹)启用trace日志。

26.2.1 颜色编码输出

如果你的终端支持ANSI,颜色输出可以用来辅助阅读。你可以为spring.output.ansi.enabled设置一个支持值来覆盖自动检测。

颜色编码用%clr转换词来配置。最简单的形式是根据日志级别进行颜色输出,例如:

1
%clr(%5p)

日志级别与颜色的映射如下:

Level Color
FATAL Red
ERROR Red
WARN Yellow
INFO Green
DEBUG Green
TRACE Green

或者,你可以通过在转换器中提供选项来指定应该试用的颜色或风格。例如,为了使文本显示黄色:

1
%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){yellow}

支持下面的颜色和风格:

  • blue
  • cyan
  • faint
  • green
  • magenta
  • red
  • yellow

26.3 文件输出

默认情况下,Spring Boot只能输出日志到控制台,不会写入日志文件。如果你想除了控制台之外还想写日志文件,你需要设置logging.filelogging.path属性(例如,在你的application.properties)。

下表显示了logging.*属性怎样在一起使用:

表 26.1. Logging属性

logging.file logging.path Example Description
(none (none) 只输出到控制台
指定文件 (none) my.log 写入指定的日志文件。名字可以是一个绝对位置或相对于当前目录。
(none) Specific directory /var/log spring.log到一个指定的目录。名字可以是一个绝对位置或相对于当前目录。

当日志文件达到10M时日志文件将循环,至于控制台输出,默认情况下只输出ERRORWARNINFO级别的信息。

日志系统在应用程序的生命周期早期进行初始化,同样地,通过@PropertySource注解加载的属性文件中将不会发现日志属性。

 

日志属性独立于真正的日志基础架构之外。因此,Spring Boot不管理特定的配置主键(例如Logback的logback.configurationFile)。

26.4 日志级别

Spring支持的所有日志系统都可以在Spring的Environment中设置日志级别(例如在application.properties设置),使用logging.level.*=LEVEL进行设置,LEVEL是TRACE,DEBUG,INFO,WARN,ERROR,FATAL,OFF中的一个。root日志器可以用logging.level.root来配置。例如在application.properties中:

1
2
3
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

默认情况下Spring Boot重新映射Thymeleaf的INFO信息,为了它们能在DEBUG级别进行输出。这能帮助减少标准日志输出中的噪声。关于怎样在你自己的配置中使用重新映射的更多细节请看LevelRemappingAppender

26.5 定制日志配置

在类路径中通过包含恰当的库可以激活各种日志系统,在类路径的根目录中提供一个合适的配置文件可以对日志系统进行更进一步的定制,或者将配置文件放在Spring Environmentlogging.config属性中指定的位置。

你可以使用系统属性org.springframework.boot.logging.LoggingSystem来强制Spring Boot使用一个特定的日志系统。它的值应该是全限定类名的LoggingSystem实现。你也可以通过使用值none来完全禁用Spring Boot的日志配置。

由于日志是在ApplicationContext创建之前初始化,因此不可能从Spring @Configuration文件中的@PropertySources来控制日志。系统属性和传统的Spring Boot外部配置文件可以工作的很好。

根据你的日志系统,将会加载下面的文件:

Logging System Customization
Logback logback-spring.xml, logback-spring.groovy, logback.xml or logback.groovy
Log4j2 log4j2-spring.xml or log4j2.xml
JDK (Java Util Logging) logging.properties

我们建议你尽可能的使用-spring变种来进行日志配置(例如,logback-spring.xml而不是logback.xml)。如果你在使用标准的配置路径,Spring不能完全控制日志的初始化。

 

在Java Java Util Logging中存在类加载问题,当从executable jar运行时会引起问题。我们建议你尽可能的避免它。

为了帮助定制一些其它属性,从Spring Environment中转移到系统属性中:

Spring Environment System Property Comments
logging.exception-conversion-word LOG_EXCEPTION_CONVERSION_WORD 当日志出现异常时会用到这个转换词。
logging.file LOG_FILE 如果定义了,会在默认的日志配置中使用。
logging.path LOG_PATH 如果定义了,会在默认的日志配置中使用。
logging.pattern.console CONSOLE_LOG_PATTERN 用在控制台中的日志模式(stdout)。(只支持默认的Logback设置。)
logging.pattern.file FILE_LOG_PATTERN 用在文件中的日志模式 (如果启用LOG_FILE)。(只支持默认的Logback设置。)
logging.pattern.level LOG_LEVEL_PATTERN 这种模式用来实施日志级别(默认%5p)。 (只支持默认的Logback设置。)
PID PID 当前的进程ID

当转换配置文件时,所有的日志系统都支持查询系统属性。例如spring-boot.jar的默认配置。

如果你在日志属性中想使用占位符,你应该试用Spring Boot的语法而不是底层框架的语法。尤其是,如果你在使用Logback,你应该使用:作为属性名和默认值之间的分隔符,而不是:-

 

你可以通过重写LOG_LEVEL_PATTERN(或Logback中的logging.pattern.level)来添加MDC和其它的专门内容来日志行中。例如,你可以使用logging.pattern.level=user:%X{user} %5p,默认的日志形式将包含MDC输入,如果它存在的话,例如:

1
2
2015-09-30 12:30:04.031 user:juergen INFO 22174 --- [  nio-8080-exec-0] demo.Controller
Handling authenticated request

26.6 Logback扩展

Spring Boot包含许多Logback的扩展,这有助于进行更高级的配置。你可以在你的logback-spring.xml配置文件中使用这些扩展。

你不能在标准的logback.xml配置文件中使用扩展,因为它加载的太早了。你需要使用logback-spring.xml或定义logging.config属性。

26.6.1 特定profile的配置

<springProfile>标签允许你自由的包含或排除基于激活的Spring profiles的配置的一部分。在<configuration>元素的任何地方都支持Profile部分。使用name属性来指定哪一个profile接受配置。多个profiles可以用一个逗号分隔的列表来指定。

1
2
3
4
5
6
7
8
9
10
11
<springProfile name="staging">
<!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev, staging">
<!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
<!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

26.6.2 Environment属性

<springProperty>标签允许你在Logback使用从Spring Environment获得的属性。如果你想在你的Logback配置中访问application.properties文件中的属性,这是非常有用的。这个标签与Logback的标准<property>标签的作用方式类似,但不是为你指定的source属性(从Environment中)指定一个直接的value。如果你需要在某个地方而不是在local作用域中存储属性,你可以使用scope属性。如果你需要一个备用值以防属性没有在Environment中设置,你可以使用defaultValue属性。

1
2
3
4
5
6
<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
<remoteHost>${fluentHost}</remoteHost>
...
</appender>

RelaxedPropertyResolver是用来访问Environment属性。如果在破折号符号中指定了source,则会尝试所有的不严格的变种(myPropertyNameMY_PROPERTY_NAME等)。

如果有收获,可以请我喝杯咖啡!